package me.zxk.smartagriculture.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zxk.smartagriculture.dto.news.NewsDetailResponse;
import me.zxk.smartagriculture.dto.news.NewsListResponse;
import me.zxk.smartagriculture.entity.Like;
import me.zxk.smartagriculture.entity.News;
import me.zxk.smartagriculture.repository.LikeRepository;
import me.zxk.smartagriculture.repository.NewsRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 新闻服务
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class NewsService {

    private final NewsRepository newsRepository;
    private final LikeRepository likeRepository;

    /**
     * 获取新闻列表
     */
    public Page<NewsListResponse> getNewsList(String keyword, Pageable pageable, Long currentUserId) {
        Page<News> newsPage;
        
        if (StringUtils.hasText(keyword)) {
            newsPage = newsRepository.findByStatusAndKeyword(keyword, pageable);
        } else {
            newsPage = newsRepository.findByStatus(1, pageable); // 1表示已发布
        }
        
        // 转换为响应DTO
        Page<NewsListResponse> responsePage = newsPage.map(NewsListResponse::fromEntity);
        
        // 如果用户已登录，设置点赞状态
        if (currentUserId != null) {
            setLikeStatus(responsePage.getContent(), currentUserId);
        }
        
        return responsePage;
    }

    /**
     * 获取新闻详情
     */
    @Transactional
    public NewsDetailResponse getNewsDetail(Long newsId, Long currentUserId) {
        News news = newsRepository.findById(newsId)
                .orElseThrow(() -> new RuntimeException("新闻不存在"));
        
        if (news.getStatus() != 1) {
            throw new RuntimeException("新闻未发布或已下线");
        }
        
        // 增加浏览数
        newsRepository.incrementViewCount(newsId);
        
        NewsDetailResponse response = NewsDetailResponse.fromEntity(news);
        response.setViewCount(news.getViewCount() + 1); // 更新响应中的浏览数
        
        // 如果用户已登录，设置点赞状态
        if (currentUserId != null) {
            boolean isLiked = likeRepository.existsByUserIdAndTargetIdAndTargetType(
                    currentUserId, newsId, Like.TargetType.NEWS);
            response.setIsLiked(isLiked);
        }
        
        return response;
    }

    /**
     * 点赞/取消点赞新闻
     */
    @Transactional
    public boolean toggleNewsLike(Long newsId, Long userId) {
        // 检查新闻是否存在
        News news = newsRepository.findById(newsId)
                .orElseThrow(() -> new RuntimeException("新闻不存在"));
        
        if (news.getStatus() != 1) {
            throw new RuntimeException("新闻未发布或已下线");
        }
        
        // 检查是否已点赞
        boolean isLiked = likeRepository.existsByUserIdAndTargetIdAndTargetType(
                userId, newsId, Like.TargetType.NEWS);
        
        if (isLiked) {
            // 取消点赞
            likeRepository.deleteByUserIdAndTargetIdAndTargetType(userId, newsId, Like.TargetType.NEWS);
            newsRepository.decrementLikeCount(newsId);
            log.info("用户 {} 取消点赞新闻: {}", userId, newsId);
            return false;
        } else {
            // 点赞
            Like like = new Like();
            like.setUserId(userId);
            like.setTargetId(newsId);
            like.setTargetType(Like.TargetType.NEWS);
            likeRepository.save(like);
            
            newsRepository.incrementLikeCount(newsId);
            log.info("用户 {} 点赞新闻: {}", userId, newsId);
            return true;
        }
    }

    /**
     * 设置新闻列表的点赞状态
     */
    private void setLikeStatus(List<NewsListResponse> newsList, Long userId) {
        if (newsList.isEmpty()) {
            return;
        }
        
        // 获取所有新闻ID
        List<Long> newsIds = newsList.stream()
                .map(NewsListResponse::getId)
                .collect(Collectors.toList());
        
        // 批量查询用户的点赞记录
        List<Like> userLikes = likeRepository.findByUserIdAndTargetIdsAndTargetType(
                userId, newsIds, Like.TargetType.NEWS);
        
        // 转换为Map便于查找
        Set<Long> likedNewsIds = userLikes.stream()
                .map(Like::getTargetId)
                .collect(Collectors.toSet());
        
        // 设置点赞状态
        newsList.forEach(news -> news.setIsLiked(likedNewsIds.contains(news.getId())));
    }
}
